package com.hruiworks.campusgroup.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hruiworks.campusgroup.common.PageVO;
import com.hruiworks.campusgroup.constants.AdministratorConstant;
import com.hruiworks.campusgroup.dao.mapper.ActivityGradeMapper;
import com.hruiworks.campusgroup.dao.mapper.AdministratorMapper;
import com.hruiworks.campusgroup.dao.mapper.UserMapper;
import com.hruiworks.campusgroup.enums.ErrorCode;
import com.hruiworks.campusgroup.exception.BusinessException;
import com.hruiworks.campusgroup.manager.ActivityGroupManager;
import com.hruiworks.campusgroup.manager.entity.ActivityData;
import com.hruiworks.campusgroup.pojo.entity.*;
import com.hruiworks.campusgroup.common.BaseUser;
import com.hruiworks.campusgroup.pojo.query.ActivityPageQuery;
import com.hruiworks.campusgroup.pojo.query.ActivityQuery;
import com.hruiworks.campusgroup.pojo.request.ActivityCreateRequest;
import com.hruiworks.campusgroup.pojo.request.ActivityUpdateRequest;
import com.hruiworks.campusgroup.service.ActivityMessageService;
import com.hruiworks.campusgroup.service.ActivityService;
import com.hruiworks.campusgroup.dao.mapper.ActivityMapper;
import com.hruiworks.campusgroup.service.NoticeService;
import com.hruiworks.campusgroup.utils.RedisUtils;
import com.hruiworks.usercheck.util.ParamUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import static com.hruiworks.campusgroup.constants.ActivityConstant.REVIEW_AGREE;
import static com.hruiworks.campusgroup.constants.ActivityConstant.REVIEW_DISAGREE;
import static com.hruiworks.campusgroup.constants.AdministratorConstant.ADMINISTRATOR_LEVEL_0;
import static com.hruiworks.campusgroup.constants.AdministratorConstant.ADMINISTRATOR_LEVEL_2;
import static com.hruiworks.campusgroup.constants.redisKey.NoticeRedisKey.NOTICE_NEW_ACTIVITY_GLOBAL_COUNT;
import static com.hruiworks.campusgroup.constants.redisKey.UniversityRedisKey.UNIVERSITY_ALL;

/**
 * @author jiushui
 * @description 针对表【activity(活动表)】的数据库操作Service实现
 * @createDate 2025-02-15 10:33:56
 */
@Service
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity>
        implements ActivityService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private ActivityMapper activityMapper;

    @Resource
    private ActivityGroupManager activityGroupManager;

    @Resource
    private ActivityGradeMapper activityGradeMapper;

    @Resource
    private NoticeService noticeService;

    @Resource
    private ActivityMessageService activityMessageService;

    @Override
    public Boolean applyForActivity(ActivityCreateRequest activityCreateRequest, Long userId) {
        // 1. 校验参数为空
        if (Objects.isNull(activityCreateRequest) || ParamUtils.isAnyBlank(activityCreateRequest)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }

        // 2. 补充参数
        Activity activity = new Activity();
        BeanUtils.copyProperties(activityCreateRequest, activity);
        User user = userMapper.selectById(userId);

        activity.setApplicant(userId);
        activity.setUniversity(user.getUniversity());

        // 3. 同一学校有没有重名活动
        LambdaQueryWrapper<Activity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Activity::getActivityName, activity.getActivityName())
                .eq(Activity::getUniversity, activity.getUniversity());
        if (Objects.nonNull(activityMapper.selectOne(queryWrapper))) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "存在同名活动");
        }


        // 4. 插入数据
        int insert = activityMapper.insert(activity);

        return insert == 1;
    }

    @Override
    public List<Activity> listActivity(ActivityQuery activityQuery) {
        String activityName = activityQuery.getActivityName();
        Integer maxNum = activityQuery.getMaxNum();
        Long applicant = activityQuery.getApplicant();
        String type = activityQuery.getType();
        Long reviewer = activityQuery.getReviewer();
        Integer activityStatus = activityQuery.getActivityStatus();
        String university = activityQuery.getUniversity();

        LambdaQueryWrapper<Activity> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(activityName)) {
            queryWrapper.like(Activity::getActivityName,activityName);
        }
        if (Objects.nonNull(maxNum)) {
            queryWrapper.eq(Activity::getMaxNum, maxNum);
        }
        if (Objects.nonNull(applicant)) {
            queryWrapper.eq(Activity::getApplicant, applicant);
        }
        if (StringUtils.isNotBlank(type)) {
            queryWrapper.eq(Activity::getType, type);
        }
        if (Objects.nonNull(reviewer)) {
            queryWrapper.eq(Activity::getReviewer, reviewer);
        }
        if (Objects.nonNull(activityStatus)) {
            queryWrapper.eq(Activity::getActivityStatus, activityStatus);
        }
        if (StringUtils.isNotBlank(university)) {
            queryWrapper.eq(Activity::getUniversity, university);
        }

        return activityMapper.selectList(queryWrapper);
    }

    @Override
    public Boolean createActivity(ActivityCreateRequest activityCreateRequest, Administrator administrator) {
        // 校验权限
        if (ADMINISTRATOR_LEVEL_0.equals(administrator.getLevel())) {
            throw new BusinessException(ErrorCode.FORBIDDEN, "root不允许对活动进行操作");
        }

        // 1. 校验参数为空
        if (Objects.isNull(activityCreateRequest) || ParamUtils.isAnyBlank(activityCreateRequest)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }

        // 2. 补充参数
        Activity activity = new Activity();
        BeanUtils.copyProperties(activityCreateRequest, activity);

        activity.setUniversity(administrator.getUniversity());
        activity.setReviewer(administrator.getId());
        // 管理员创建直接同意
        activity.setActivityStatus(REVIEW_AGREE);


        // 3. 同一学校有没有重名活动
        LambdaQueryWrapper<Activity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Activity::getActivityName, activity.getActivityName())
                .eq(Activity::getUniversity, activity.getUniversity());
        if (Objects.nonNull(activityMapper.selectOne(queryWrapper))) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "存在同名活动");
        }


        // 4. 插入数据
        int insert = activityMapper.insert(activity);

        if (insert == 1) {
            // 插入存储活动上线消息
            activityMessageService.releaseActivityMessage(activity);

            // 数据库缓存更新
            Object schoolKey = RedisUtils.hashGet(UNIVERSITY_ALL, activity.getUniversity());
            RedisUtils.hashIncrBy(NOTICE_NEW_ACTIVITY_GLOBAL_COUNT, schoolKey.toString(), 1L);

            // 通知给用户
            noticeService.newActivityNoticeInstant(activity);
        }

        return insert == 1;
    }

    @Override
    public List<Activity> listActivity(ActivityQuery activityQuery, BaseUser baseUser) {

        // 1. 根据身份和权限限制查询范围
        if (baseUser instanceof User user) {
            activityQuery.setUniversity(user.getUniversity());
        }
        else if (baseUser instanceof Administrator administrator) {
            if (administrator.getLevel().equals(ADMINISTRATOR_LEVEL_0)) {
                return Lists.newArrayList();
            } else {
                activityQuery.setUniversity(administrator.getUniversity());
            }
        } else {
            throw new BusinessException(ErrorCode.OTHER_ERROR, "baseUser校验出错");
        }
        // 查询
        return listActivity(activityQuery);
    }

    @Override
    public Boolean reviewActivity(Long activityId, Integer reviewStatus, Administrator administrator) {
        // 1. 鉴权
        if (ADMINISTRATOR_LEVEL_0.equals(administrator.getLevel())) {
            throw new BusinessException(ErrorCode.FORBIDDEN,"root管理员不应具有相关权限");
        }
        // 2. 更新活动状态
        if (!(reviewStatus.equals(REVIEW_AGREE) || reviewStatus.equals(REVIEW_DISAGREE))) {
           throw new BusinessException(ErrorCode.PARAMS_ERROR, "活动状态不存在");
        }
        Activity activity = new Activity();
        activity.setId(activityId);
        activity.setActivityStatus(reviewStatus);
        activity.setReviewer(administrator.getId());
        int i = activityMapper.updateById(activity);
        Activity activityNew = activityMapper.selectById(activityId);
        if (reviewStatus.equals(REVIEW_AGREE)) {
            // 插入存储活动上线消息
            activityMessageService.releaseActivityMessage(activityNew);
            // 通知给用户
            noticeService.newActivityNoticeInstant(activityNew);
        }
        return i == 1;
    }

    @Override
    public Boolean updateActivity(ActivityUpdateRequest activityUpdateRequest, Administrator administrator) {

        // 1. 鉴权
        if (ADMINISTRATOR_LEVEL_0.equals(administrator.getLevel())) {
            throw new BusinessException(ErrorCode.FORBIDDEN,"root管理员不应具有相关权限");
        }
        // 2. 清理空字符串
        ParamUtils.toNull(activityUpdateRequest);
        // 3. 更新
        Activity activity = new Activity();
        BeanUtils.copyProperties(activityUpdateRequest, activity);
        int i = activityMapper.updateById(activity);
        return i == 1;
    }

    @Override
    public Boolean deleteActivity(Long activityId, Administrator administrator) {
        // 1. 鉴权
        if (ADMINISTRATOR_LEVEL_0.equals(administrator.getLevel())) {
            throw new BusinessException(ErrorCode.FORBIDDEN,"root管理员不应具有相关权限");
        }
        if (ADMINISTRATOR_LEVEL_2.equals(administrator.getLevel())) {
            throw new BusinessException(ErrorCode.FORBIDDEN,"level2管理员不具备删除活动权限");
        }
        // 2. 先查一下该活动是不是管理员所管理的学校的，再进行删除，否则其他管理员调用api也能删除
        Activity activity = activityMapper.selectById(activityId);
        if (Objects.isNull(activity)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "不存在该活动");
        }
        if (!administrator.getUniversity().equals(activity.getUniversity())) {
            throw new BusinessException(ErrorCode.FORBIDDEN, "没有该学校的权限");
        }
        int i = activityMapper.deleteById(activityId);
        return i == 1;
    }

    @Override
    public PageVO<Activity> listPageActivity(ActivityPageQuery activityPageQuery, BaseUser baseUser) {

        // 1. 校验部分参数
        if (Objects.isNull(activityPageQuery.getCurrent()) || Objects.isNull(activityPageQuery.getSize())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "缺少分页参数");
        }
        // 2. 根据身份和权限限制查询范围
        if (baseUser instanceof User user) {
            activityPageQuery.setUniversity(user.getUniversity());
        }
        else if (baseUser instanceof Administrator administrator) {
            if (administrator.getLevel().equals(ADMINISTRATOR_LEVEL_0)) {
                PageVO<Activity> activityPageVO = new PageVO<>();
                activityPageVO.setRecords(Lists.newArrayList());
                activityPageVO.setTotal(0L);
                activityPageVO.setSize(activityPageQuery.getSize());
                activityPageVO.setCurrent(activityPageQuery.getCurrent());
                return activityPageVO;
            } else {
                activityPageQuery.setUniversity(administrator.getUniversity());
            }
        } else {
            throw new BusinessException(ErrorCode.OTHER_ERROR, "baseUser校验出错");
        }

        return listPageActivity(activityPageQuery);
    }

    @Override
    public PageVO<Activity> listPageActivity(ActivityPageQuery activityPageQuery) {
        if (Objects.isNull(activityPageQuery.getCurrent()) || Objects.isNull(activityPageQuery.getSize())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "缺少分页参数");
        }
        String activityName = activityPageQuery.getActivityName();
        Integer maxNum = activityPageQuery.getMaxNum();
        Long applicant = activityPageQuery.getApplicant();
        String type = activityPageQuery.getType();
        Long reviewer = activityPageQuery.getReviewer();
        Integer activityStatus = activityPageQuery.getActivityStatus();
        String university = activityPageQuery.getUniversity();

        LambdaQueryWrapper<Activity> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(activityName)) {
            queryWrapper.like(Activity::getActivityName,activityName);
        }
        if (Objects.nonNull(maxNum)) {
            queryWrapper.eq(Activity::getMaxNum, maxNum);
        }
        if (Objects.nonNull(applicant)) {
            queryWrapper.eq(Activity::getApplicant, applicant);
        }
        if (StringUtils.isNotBlank(type)) {
            queryWrapper.eq(Activity::getType, type);
        }
        if (Objects.nonNull(reviewer)) {
            queryWrapper.eq(Activity::getReviewer, reviewer);
        }
        if (Objects.nonNull(activityStatus)) {
            queryWrapper.eq(Activity::getActivityStatus, activityStatus);
        }
        if (StringUtils.isNotBlank(university)) {
            queryWrapper.eq(Activity::getUniversity, university);
        }

        LocalDateTime now = LocalDateTime.now();
        queryWrapper.gt(Activity::getExpirationTime,now);
        Page<Activity> queryPage = new Page<>();
        queryPage.setSize(activityPageQuery.getSize());
        queryPage.setCurrent(activityPageQuery.getCurrent());
        Page<Activity> page = activityMapper.selectPage(queryPage, queryWrapper);
        PageVO<Activity> activityPageVO = new PageVO<>();
        activityPageVO.setRecords(page.getRecords());
        activityPageVO.setTotal(page.getTotal());
        activityPageVO.setSize(page.getSize());
        activityPageVO.setCurrent(page.getCurrent());
        return activityPageVO;
    }

    @Override
    public Activity oneActivity(Long activityId) {
        Activity activity = activityMapper.selectById(activityId);
        if (Objects.isNull(activity)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "不存在该活动");
        }
        return activity;
    }

    @Override
    public PageVO<ActivityData> selfHistoryActivityData(Long size, Long current,String searchValue, User user) {
        return activityGroupManager.listActivityDataPageSelf(size, current,searchValue, user);
    }

    @Override
    public Boolean updateActivityGrade() {
        Long startId = 0L;
        Long limit = 1L;
        List<Long> targetIdList = activityMapper.limitGreaterThanActivityId(startId, limit);
        if (targetIdList.isEmpty()) {
            return false;
        }
        Long targetId = targetIdList.get(0);
        while (true) {
            // 1. 找到对应的相关评分
            LambdaQueryWrapper<ActivityGrade> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(ActivityGrade::getActivityId, targetId);

            List<ActivityGrade> activityGrades = activityGradeMapper.selectList(lambdaQueryWrapper);
            // 评价大于100数再进行平均分数值
            if (activityGrades.size() > 100) {
                int sum = activityGrades.stream().mapToInt(ActivityGrade::getGrade).sum();
                BigDecimal newGrade = new BigDecimal(sum).divide(new BigDecimal(activityGrades.size()), 2, RoundingMode.HALF_UP);
                Activity activity = new Activity();
                activity.setId(targetId);
                activity.setGrade(newGrade);
                activityMapper.updateById(activity);
            }

            List<Long> list = activityMapper.limitGreaterThanActivityId(targetId, limit);
            if (list.isEmpty()) {
                break;
            } else {
                targetId = list.get(0);
            }
        }

        return true;
    }
}




